﻿using System.Globalization;
using System.Text.RegularExpressions;
using System.Windows.Input;

namespace BrasilFramework.Controle.Silverlight.Comum
{
    public class EventoTeclado
    {

        private static string ReplicarTexto(string texto, int quantidade)
        {
            string textoReplicado = string.Empty;
            for (int i = 0; i < quantidade; i++)
                textoReplicado += texto;

            return textoReplicado;
        }

        public static string RetornarApenasNumeros(string texto, bool negativo)
        {
            string sinalNegativo = (negativo ? @"\" + NumberFormatInfo.CurrentInfo.NegativeSign : string.Empty);
            return Regex.Replace(texto, string.Format(@"[^0-9{0}]", sinalNegativo), string.Empty);
        }

        public static void CampoApenasNumero(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter || Keyboard.Modifiers == ModifierKeys.Shift) return;
            if (!VerificarDigito(e.Key)) e.Handled = true;
        }

        public static void CampoNumerico(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter || Keyboard.Modifiers == ModifierKeys.Shift) return;

            string valorAtual = "-";
            bool negativo = false;

            if (sender != null && sender.GetType() == typeof(TextBox))
            {
                var controlePai = (TextBox)sender;
                if(!controlePai.IsEnabled || controlePai.IsReadOnly) return;
                valorAtual = controlePai.Text;
                negativo = controlePai.Negativo;
            }

            if (!VerificarDigito(e.Key)
                && !VerificarTeclaEspecial(RetornarTecla(e), valorAtual, negativo)
                && !VerificarTeclaAreaTransferencia(e.Key))
                e.Handled = true;
        }

        public static Key RetornarTecla(KeyEventArgs e)
        {
            if (e.Key != Key.Unknown) return e.Key;

            switch (e.PlatformKeyCode)
            {
                case 188:
                    return Key.Decimal;
                case 189:
                    return Key.Subtract;
                default:
                    return e.Key;
            }
        }

        public static bool VerificarDigito(Key tecla)
        {
            if (Keyboard.Modifiers == ModifierKeys.Shift) return false;

            if (tecla < Key.D0 || tecla > Key.D9)
                if (tecla < Key.NumPad0 || tecla > Key.NumPad9)
                    if (tecla != Key.Back && tecla != Key.Tab)
                        return false;

            return true;
        }

        public static bool VerificarTeclaEspecial(Key tecla, string valorAtual, bool aceitaNegativo)
        {
            if (Keyboard.Modifiers == ModifierKeys.Shift) return false;

            switch (tecla)
            {
                case Key.Subtract:
                    return (valorAtual.Length == 0 && aceitaNegativo);
                case Key.Decimal:
                    return (valorAtual.IndexOf(NumberFormatInfo.CurrentInfo.NumberDecimalSeparator) < 0);
                case Key.Left:
                case Key.Right:
                case Key.Home:
                case Key.End:
                case Key.Back:
                case Key.Ctrl:
                case Key.Tab:
                    return true;
                default:
                    return false;
            }
        }

        public static bool VerificarTeclaAreaTransferencia(Key tecla)
        {
            if (Keyboard.Modifiers != ModifierKeys.Control) return false;

            switch (tecla)
            {
                case Key.C:
                case Key.X:
                case Key.V:
                    return true;
                default:
                    return false;
            }
        }

        public static string Formatar(string texto, string mascara)
        {
            string newStr = texto;
            string retStr = "";

            if (string.IsNullOrEmpty(texto) || string.IsNullOrEmpty(mascara)) return texto;

            newStr = Regex.Replace(newStr, ExpressaoRegular.RE_SEPARADORES, string.Empty);

            for (int i = 0, l = 0; i < mascara.Length && l < newStr.Length; i++)
            {
                if (Regex.IsMatch(mascara[i].ToString(), ExpressaoRegular.RE_SEPARADORES))
                    retStr += mascara[i];
                else
                {
                    if (mascara[i] == '#' && Regex.IsMatch(newStr[l].ToString(), ExpressaoRegular.RE_NUMERO))
                        retStr += newStr[l++];
                    else if (mascara[i] == '?' && Regex.IsMatch(newStr[l].ToString(), ExpressaoRegular.RE_LETRA))
                        retStr += newStr[l++];
                    else if (mascara[i] == '*')
                        retStr += newStr[l++];
                }
            }

            return retStr;
        }

        public static string FormatarNumero(string texto, int quantidadeCasasDecimais, bool negativo)
        {
            int tamanhoMaximoDecimal = decimal.MaxValue.ToString().Length - 1;

            NumberFormatInfo informacaoNumero = NumberFormatInfo.CurrentInfo;

            if (quantidadeCasasDecimais == 0 || texto.Length == 0 || texto == informacaoNumero.NegativeSign) return texto;

            string textoAux = RetornarApenasNumeros(texto, negativo);

            if (textoAux.Length == 0) return textoAux;

            //Excedeu Tamanho Máximo Número
            if (texto.Length > tamanhoMaximoDecimal) textoAux = textoAux.Substring(0, tamanhoMaximoDecimal);

            int quantidadeSinalNegativo = texto[0].ToString() == informacaoNumero.NegativeSign ? 1 : 0;
            bool decimalInformado = texto.IndexOf(informacaoNumero.NumberDecimalSeparator) > -1;
            if (!decimalInformado && quantidadeCasasDecimais > 0)
                textoAux += ReplicarTexto("0", quantidadeCasasDecimais);

            if (textoAux.Length > (quantidadeCasasDecimais + quantidadeSinalNegativo))
            {
                textoAux = textoAux.Replace(informacaoNumero.NumberDecimalSeparator, string.Empty);
                textoAux = textoAux.Insert(textoAux.Length - quantidadeCasasDecimais, informacaoNumero.NumberDecimalSeparator);
                textoAux = decimal.Parse(textoAux).ToString("N" + quantidadeCasasDecimais).Replace(informacaoNumero.NumberGroupSeparator, string.Empty);
            }

            return textoAux;

        }

    }
}